package com.xcity.game.turntable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.db.entity.Player;
import com.xcity.game.ISystem;
import com.xcity.game.adventure.AdventureService;
import com.xcity.game.common.Cause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.common.PlayerPool;
import com.xcity.game.event.GameEvents;
import com.xcity.game.item.ItemEffect;
import com.xcity.game.item.ItemInfo;
import com.xcity.game.vip.VipTemplate;
import com.xcity.game.vip.VipUtils;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.request.TurntableInitRequest;
import com.xcity.pomelo.request.TurntableRollRequest;
import com.xcity.pomelo.response.HintResponse;
import com.xcity.pomelo.response.TurnTableInfoResponse;
import com.xcity.pomelo.response.TurnTableRollResponse;
import com.xcity.util.SessionUtils;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.game.time.TimeUpdater;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.Service;
import naga.x.service.ServiceException;
import naga.x.util.CommonUtils;

/**
 * 奇遇v1
 * @see AdventureService
 * @author yang.li
 *
 */
@Deprecated
@OPHandler
public class TurnTableService implements Service, MessageConst, PlayerPool, ISystem {

	protected List<TurnTableTemplate> templates;
	
	private static final int DICE_MAX_POINT = 6; // 骰子最大点数
	private static final int GRID_SIZE = 20; // 格子总数(其中第1个格子为40001物品,第11个格子为40000物品)
//	private static final int LEVEL_LIMIT = 1;
	private static final int FREE_TIMES = 1; // 每轮免费次数
	private static final int COST_GOLD = 15000;
	
	private static final int POS_DOUBLE_REWARD = 10; // 双倍奖励物品位置(索引从0开始)
	private static final int FIRST_GRID_ITEM_ID = 40001; // 第1个格子中的物品(小红旗)
	private static final int DOUBLE_REWARD_ITEM_ID = 40000; // 双倍奖励物品id(奇遇双倍奖励)
	private static final ItemInfo FIRST_GRID_ITEM = new ItemInfo(FIRST_GRID_ITEM_ID, 1);
	private static final ItemInfo DOUBLE_REWARD_ITEM = new ItemInfo(DOUBLE_REWARD_ITEM_ID, 1);
	
	static final Logger LOG = LoggerFactory.getLogger(TurnTableService.class);
	
	@Override
	public void startup() throws ServiceException {
		templates = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(TurnTableTemplate.class);
	}

	@Override
	public void shutdown() throws ServiceException {
	}

	@Override
	public String getId() {
		return getClass().getName();
	}
	
	@PomeloOP(PomeloRoute.TURNTABLE_INIT)
	protected void requestInit(Session session, TurntableInitRequest req) {
		Player player = session.getClient();
//		if (player.getLevel() < LEVEL_LIMIT) {
//			session.send(new HintResponse(req.getSerial(), TURN_TABLE_LEVEL_NOT_REACH));
//			return;
//		}
		if (player.getBag().getFreeSize() < 2) {
			session.send(new HintResponse(req.getSerial(), BAG_FULL));
			return;
		}
		int freeTimes = getFreeTimes(player, true);
		List<ItemInfo> items = getItems(player);
		int pos = player.getPool().getIntValue(PROPERTY_LAST_ROLL_POSTION);
		TurnTableInfoResponse res = new TurnTableInfoResponse(req.getSerial(), freeTimes, pos, COST_GOLD, items);
		session.send(res);
	}
	
	private List<ItemInfo> getItems(Player player) {
		List<ItemInfo> items = player.getPool().getList(PROPERTY_TURN_TABLE_ITEMS, ItemInfo.class);
		if (items == null) {
			items = refresh(player);
		}
		return items;
	}
	
	private ItemInfo getReward(Player player) {
		int pos = player.getPool().getIntValue(PROPERTY_LAST_ROLL_POSTION);
		if (pos <= 0) { // 第1个格子中的物品不给(小红旗)
			return null;
		}
		List<ItemInfo> items = getItems(player);
		if (items == null || pos >= items.size()) {
			return null;
		}
		return items.get(pos);
	}
	
	private int getFreeTimes(Player player, boolean reset) {
		int usedTimes = player.getPool().getIntValue(PROPERTY_ROLL_TIMES);
		if (reset) {
			int lastRollDay = player.getPool().getIntValue(PROPERTY_LAST_ROLL_DAY);
			int today = TimeUpdater.getInstance().today();
			if (today != lastRollDay) {
				// 重置数据
				player.poolSet(PROPERTY_LAST_ROLL_DAY, today);
				player.poolSet(PROPERTY_LAST_ROLL_POSTION, 0);
				player.poolSet(PROPERTY_ROLL_TIMES, 0);
				refresh(player);
				usedTimes = player.getPool().getIntValue(PROPERTY_ROLL_TIMES);
			}
		}
		VipTemplate vt = VipUtils.getTemplate(player.getVipLvl());
		int totalFreeTimes = FREE_TIMES;
		if (vt != null) {
			totalFreeTimes += vt.getTurntableFreeNum();
		}
		int leftFreeTimes = totalFreeTimes - usedTimes;
		return leftFreeTimes > 0 ? leftFreeTimes : 0;
	}
	
	/**
	 * 刷新转盘上的物品
	 * @return
	 */
	private List<ItemInfo> refresh(Player player) {
		List<TurnTableTemplate> temps = templates;
		List<ItemInfo> result = new ArrayList<ItemInfo>(GRID_SIZE);
		for (int i = 0, size = temps.size(); i < size; i++) {
			TurnTableTemplate temp = temps.get(i);
			List<ItemInfo> items = new ArrayList<ItemInfo>(temp.getItemList());
			boolean remove = items.size() >= temp.getCount();
			for (int j = 0; j < temp.getCount(); j++) {
				int pos = CommonUtils.randomInt(items.size());
				result.add(remove ? items.remove(pos).clone() : items.get(pos).clone()); // 需要clone,因为要改变数量
			}
		}
		Collections.shuffle(result, CommonUtils.RND);
		result.add(0, FIRST_GRID_ITEM); // 第1个格子插入物品:小红旗(不用clone,不会获得该物品,只是客户端展示用)
		result.add(POS_DOUBLE_REWARD, DOUBLE_REWARD_ITEM.clone()); // 第11个格子插入双倍奖励物品
		player.poolSet(PROPERTY_TURN_TABLE_ITEMS, result);
		VipTemplate vt = VipUtils.getTemplate(player.getVipLvl());
		int vipFreeTimes = vt != null ? vt.getTurntableFreeNum() : 0;
		int n = player.getPool().getIntValue(PROPERTY_ROLL_TIMES);
		player.poolSet(PROPERTY_ROLL_TIMES, vipFreeTimes < n ? vipFreeTimes : n); // 每轮重置次数
		return result;
	}
	
	@PomeloOP(PomeloRoute.TURNTABLE_ROLL)
	protected void requestRoll(Session session, TurntableRollRequest req) {
		Player player = session.getClient();
		if (player.getBag().getFreeSize() < 2) {
			session.send(new HintResponse(req.getSerial(), BAG_FULL));
			return;
		}
		if (getFreeTimes(player, false) <= 0 && !player.costGold(COST_GOLD, Cause.TURNTABLE)) {
			player.send(new HintResponse(req.getSerial(), GOLD_NOT_ENOUGH));
			return;
		}
		if (SessionUtils.isOperateTooFrequent(session, SessionUtils.LAST_TURNTABLE_TIME)) {
			session.send(new HintResponse(req.getSerial(), MessageConst.OPERATE_TOO_FREQUENT));
			return;
		}
		int point = CommonUtils.randomInt(1, DICE_MAX_POINT);
		int pos = player.getPool().getIntValue(PROPERTY_LAST_ROLL_POSTION);
		boolean isDouble = POS_DOUBLE_REWARD == pos;
		pos += point;
		player.poolAdd(PROPERTY_ROLL_TIMES, 1);
		if (pos >= GRID_SIZE) {
			// 回到起始点，并刷新转盘物品
			pos = 0;
			refresh(player);
			App.getApp().getEventManager().addEvent(GameEvents.EVENT_TURNTABLE_PLAY_CYCLE, player);
		}
		player.poolSet(PROPERTY_LAST_ROLL_POSTION, pos);
		ItemInfo reward = getReward(player);
		byte rewardType = TurnTableRollResponse.NO_REWARD;
		if (reward != null) {
			if (reward.getId() != DOUBLE_REWARD_ITEM_ID) {
				player.getBag().addItemWithoutException(reward.getId(), isDouble ? reward.getCount() * 2 : reward.getCount(), Cause.TURNTABLE);
			}
			reward.setCount(0); // 置空
			int effect = reward.getTemplate().getEffect();
			switch (effect) {
				case ItemEffect.ADD_GOLD:
					rewardType = TurnTableRollResponse.GOLD_REWARD;
					break;
				case ItemEffect.ADD_STONE:
					rewardType = TurnTableRollResponse.STONE_REWARD;
					break;
				default:
					rewardType = TurnTableRollResponse.ITEM_REWARD;
					break;
			}
		}
		TurnTableRollResponse res = new TurnTableRollResponse(req.getSerial(), getFreeTimes(player, false), point, COST_GOLD, rewardType);
		session.send(res);
		App.getApp().getEventManager().addEvent(GameEvents.EVENT_USE_SYSTEM, player, getSystemId());
		LOG.info("[TURNTABLE]ID[{}]ITEM[{}]POINT[{}]POS[{}]DOUBLE[{}]", player.getId(), reward, point, pos, isDouble);
	}

	@Override
	public int getSystemId() {
		return SYS_TRUNTABLE;
	}

}
